package com.byd.base;

import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.byd.utils.Lg;

public abstract class BaseAdapter<T, H extends BaseHolder> extends android.widget.BaseAdapter {
	protected final Context mContext;
	private final LayoutInflater mInflater;
	private final ArrayList<H> mHolders;
	protected List<T> mList;
	protected T mSelect;
	private long mLastTime;
	private final Handler mHandler = new Handler(Looper.getMainLooper());

	private String getTagStr() {
		return Lg.BASE_TAG + getClass().getSimpleName() + "(" + Integer.toHexString(hashCode()) + ")";
	}

	protected void v(Object msg) {
		Lg.v(getTagStr(), msg);
	}

	protected void d(Object msg) {
		Lg.d(getTagStr(), msg);
	}

	protected void i(Object msg) {
		Lg.i(getTagStr(), msg);
	}

	protected void w(Object msg) {
		Lg.w(getTagStr(), msg);
	}

	protected void e(Object msg) {
		Lg.e(getTagStr(), msg);
	}

	protected void wtf(Object msg) {
		Lg.wtf(getTagStr(), msg);
	}

	public BaseAdapter(Context context) {
		v("onCreate");
		mContext = context;
		mHolders = new ArrayList<H>();
		mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	}

	public void update(List<T> data) {
		mList = data;
		notifyDataSetChanged();
	}

	@Override
	public int getCount() {
		if(mList != null) {
			return mList.size();
		}
		return 0;
	}

	@Override
	public T getItem(int position) {
		if(position >= 0 && position < getCount()) {
			return mList.get(position);
		}
		return null;
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	public List<T> getData() {
		return mList;
	}

	@Override
	@SuppressWarnings("unchecked")
	public View getView(int position, View convertView, ViewGroup parent) {
		H holder;
//		v("getView: " + (convertView == null ? "null" : Integer.toHexString(convertView.hashCode())) + ", " + position);
		if(convertView == null) {
			convertView = mInflater.inflate(onInflateView(position), null);
			holder = onCreateHolder(convertView, position);
			mHolders.add(holder);
			convertView.setTag(holder);
		}
		else {
			holder = (H) convertView.getTag();
		}
		holder.convertView = convertView;
		holder.position = position;
		onUpdate(holder, position);
		return convertView;
	}

	public abstract int onInflateView(int position);

	public abstract H onCreateHolder(View convertView, int position);

	public abstract void onUpdate(H holder, int position);

	protected synchronized H getHolder(int position) {
		for (final H holder : mHolders) {
			if(holder.position == position && holder.isUse()) {
				return holder;
			}
		}
		return null;
	}

	/** 鍗曠嫭鏇存柊鏌愪竴椤� */
	public void updateItem(int position) {
		if(Looper.myLooper() == Looper.getMainLooper()) {
			final H h = getHolder(position);
			if(h != null) {
				onUpdate(h, position);
			}
		}
		else {
			post(new UpdateItem(position));
		}
	}

	/** 鍗曠嫭鏇存柊鏌愪竴椤� */
	public synchronized void updateItem(T t) {
		final int position = mList.indexOf(t);
		updateItem(position);
	}

	@Override
	public void notifyDataSetChanged() {
		if(Looper.myLooper() == Looper.getMainLooper()) {
			super.notifyDataSetChanged();
		}
		else {
			final long time = System.currentTimeMillis();
			if(time - mLastTime > 200) {// 鑷冲皯200ms鏇存柊涓�娆�
				mLastTime = time;
				postSingle(update);
			}
			else {
				// 闃叉棰戠箒鍒锋柊瀵艰嚧鍗￠】
				postSingleDelayed(update, 50);
			}
		}
	}

	private final Runnable update = new Runnable() {
		@Override
		public void run() {
			notifyDataSetChanged();
		}
	};

	private class UpdateItem implements Runnable {
		int position;

		public UpdateItem(int position) {
			this.position = position;
		}

		@Override
		public void run() {
			updateItem(position);
		}
	}

	public void setSelect(T e) {
		if(mSelect != e) {
			mSelect = e;
			notifyDataSetChanged();
		}
	}

	public void setSelect(int position) {
		setSelect(getItem(position));
	}

	public T getSelect() {
		return mSelect;
	}

	public int getSelectIndex() {
		if(mList != null) {
			return mList.indexOf(mSelect);
		}
		return -1;
	}
	
	public Resources getResources() {
		return mContext.getResources();
	}

	public final int getColor(int id) {
		return getResources().getColor(id);
	}
	
	public boolean getBoolean(int id) {
		return getResources().getBoolean(id);
	}

	public final float getDimension(int id) {
		return getResources().getDimension(id);
	}

	public final int getDimensionPixelOffset(int id) {
		return getResources().getDimensionPixelOffset(id);
	}

	public final int getDimensionPixelSize(int id) {
		return getResources().getDimensionPixelSize(id);
	}

	public final Drawable getDrawable(int id) {
		return getResources().getDrawable(id);
	}

	public final String getString(int id) {
		return getResources().getString(id);
	}

	public final String[] getStringArray(int id) {
		return getResources().getStringArray(id);
	}

	public final int getInteger(int id) {
		return getResources().getInteger(id);
	}

	public final int[] getIntArray(int id) {
		return getResources().getIntArray(id);
	}

	public final DisplayMetrics getDisplayMetrics() {
		return getResources().getDisplayMetrics();
	}

	public final Configuration getConfiguration() {
		return getResources().getConfiguration();
	}

	public final boolean post(Runnable r) {
		return mHandler.post(r);
	}

	public final boolean postSingle(Runnable r) {
		mHandler.removeCallbacks(r);
		return mHandler.post(r);
	}

	public final boolean postDelayed(Runnable r, long delayMillis) {
		return mHandler.postDelayed(r, delayMillis);
	}

	public final boolean postSingleDelayed(Runnable r, long delayMillis) {
		mHandler.removeCallbacks(r);
		return mHandler.postDelayed(r, delayMillis);
	}

	public final void removeCallbacks(Runnable r) {
		mHandler.removeCallbacks(r);
	}

	@Override
	protected void finalize() throws Throwable {
		i("finalize: " + toString());
		super.finalize();
	}
}
